package logmerger.main;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

public abstract class FileMergeUtil {
	private static final Pattern DATE_PATTERN1 = Pattern.compile("(\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}\\])");
	
	public static void mergeFiles(String filePath, String filePrefix){
		File directory = new File(filePath);
		File[] files = filterFiles(directory.listFiles(), filePrefix);
		TreeSet<LogEntry> entries = new TreeSet<LogEntry>(new LogEntryComparator());
		for(File file : files){
			entries.addAll(readEntries(file));
		}
		if(entries.size() > 0){
			mergeAndSave(entries, filePath, filePrefix, files);
		}
	}
	
	private static void mergeAndSave(Set<LogEntry> entries, String filePath, String prefix, File[] files){
		try {
			//BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + prefix + ".merged.log"));
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath + prefix + ".merged.log"));
			HashMap<String, FileChannel> fileMap = new HashMap<String, FileChannel>();
			for(File file : files){
				FileInputStream fis = new FileInputStream(file);
				fileMap.put(file.getName(), fis.getChannel());
			}
			
			for(LogEntry le : entries){
				FileChannel fc = fileMap.get(le.getFileName());
				fc.position(le.getStartPosition());
				ByteBuffer bb = ByteBuffer.allocate(le.getEntryLength());
				fc.read(bb);
				bos.write(bb.array());
			}
			
			bos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private static List<LogEntry> readEntries(File file){
		ArrayList<LogEntry> entryList = new ArrayList<LogEntry>();
		SimpleDateFormat sdf = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss.SSS]");
		int position = 0;
		String fileName = file.getName();
		
		try {
			Scanner scanner = new Scanner(file);
			scanner.useDelimiter(DATE_PATTERN1);
			
			String input = "";
			String date = "";
			while(scanner.hasNext()){
				date = scanner.findWithinHorizon(DATE_PATTERN1, 0);
				input = scanner.next();
				String totalEntry = date + input;
				byte[] byteBuffer = totalEntry.getBytes();
				LogEntry le = new LogEntry();
				le.setEntryDate(sdf.parse(date));
				le.setEntryLength(byteBuffer.length);
				le.setStartPosition(position);
				le.setFileName(fileName);
				entryList.add(le);
				
				position += byteBuffer.length;
			}
			scanner.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return entryList;
	}
	
	private static void splitBuffer(byte[] buffer){
		String bufferStr = new String(buffer);
		int relativePosition = 0;
		
		
		int length = bufferStr.length();
		for(int i = 0; i < length; i++){
			char c = bufferStr.charAt(i);
		}
	}
	
	private static File[] filterFiles(File[] files, String prefix){
		ArrayList<File> returnList = new ArrayList<File>();
		File[] returnArray = new File[0];
		
		for(File file : files){
			String fileName = file.getName();
			if(fileName.startsWith(prefix)){
				returnList.add(file);
			}
		}
		
		return returnList.toArray(returnArray);
	}
}
